# @Time    : 2020/9/27 10:15
# @Author  : Del Fung
# @File    : data_change.py
# @Software: PyCharm
# 数据解析类，运行每一个case前的前置处理中进行，返回一条完整的case信息，只对请求信息进行处理，不对描述，全局变量设置等及进行处理
import ast
import re
from .api import data_depot
from utils import string2pym, string2wbm, get_str_now_datetime, log


class DataChange(object):
    """
    数据变更类，用于将标记数据等数据转换成真实有效的数据
    """

    def convertor_(self, data: dict, sql_helper) -> dict:
        data_dict = {}
        seq_dict = {}
        sequence = data.pop('sequence')
        expected = data.pop('expected')
        if sequence:
            for seq_sql in self.str2list(sequence):
                seq_dict[seq_sql[0]] = str(sql_helper.nextval(f'{seq_sql[1]}'))
        if expected:
            expected_list = self.str2list(expected)
            data_dict['expected'] = expected_list
        for key, value in data.items():
            if '$' in value:
                data_dict[key] = self._tag_analysis(value, sql_helper, seq_dict)
            elif value == '':
                pass
            else:
                data_dict[key] = self._data_type_conversion(value)
        return data_dict

    def _tag_analysis(self, tag_data, sql_helper, seq=None):
        """
        标签数据转换，将含有标签的数据转化成真实的完整的数据
        :param tag_data: 标签
        :param seq sequence 值
        :return: 真实的数据
        """
        all_tag_list = re.findall(r'\$.*?}', tag_data)
        if len(all_tag_list) == len(re.findall(r'\$.*?{', tag_data)):
            for tag in all_tag_list:
                if 'pym' in tag[0:5]:
                    tag_data = tag_data.replace(tag, string2pym(tag[5:-1]))
                elif 'wbm' in tag[0:5]:
                    tag_data = tag_data.replace(tag, string2wbm(tag[5:-1]))
                elif 'time' in tag[0:6]:
                    tag_data = tag_data.replace(tag, get_str_now_datetime())
                elif 'seq' in tag[0:5]:
                    tag_data = tag_data.replace(tag, seq.get(tag[5:-1]))
                elif 'sql' in tag[0:5]:
                    sql_column_names = re.split(",", re.findall(r'SELECT (.*?) FROM', tag[5:-1])[0])
                    sql_values = sql_helper.query(tag[5:-1])[0]
                    if sql_values:
                        if len(sql_column_names) == 1:
                            tag_data = sql_values[sql_column_names[0]]
                        else:
                            tag_data = []
                            for column_name in sql_column_names:
                                tag_data.append(sql_values[column_name])
                else:
                    tag_data = tag_data.replace(tag, str(data_depot.get('GLOBALS', tag[2:-1])))
        else:
            raise ValueError(f'参数{tag_data}中大括号标记不是成对出现的请检查case')
        return self._data_type_conversion(tag_data)

    def _data_type_conversion(self, data) -> str or dict or list:
        """
        数据类型转换，string类型的所有数据转换成对应的格式
        :param data: [必须] ，需要转换类型的数据
        :return:真实的数据
        """
        try:
            if isinstance(data, str):
                if re.findall(r'^[{](.*)[}]$', data) or re.findall(r'^[[](.*)[]]$', data):  # ast str转list和dict
                    _real_data = ast.literal_eval(data)
                elif '=' in data and ';' != data[-1]:
                    _real_data = dict(i.split('=') for i in data.split(','))  # 将a=b,c=d 转化成字典
                elif ';' == data[-1]:
                    _real_data = self.str2list(data)
                else:
                    _real_data = data
            else:
                _real_data = data
            return _real_data
        except SyntaxError:
            log.error(f"解析数据{data}，时发生错误，请检查数据!")
            raise SyntaxError(f"解析数据{data}，时发生错误，请检查数据!")
        except ValueError:
            log.error(f"解析数据{data}，时发生错误，请检查数据!")
            raise ValueError(f"解析数据{data}，时发生错误，请检查数据!")

    @staticmethod
    def str2list(source: str) -> list:

        """
        将str转成list 格式(data1=$.data2;) 第一个数据，第二个数据;
        :param source: （必须） 源数据
        :return: 当源数据为空的直接返回空，当不为空的时候转换成[[=,data1,data2]...]
        """
        if source:
            try:
                data_list = []
                for data in list(filter(lambda x: x, re.split(';', source))):
                    _temp_list = re.split(',', data)
                    if len(_temp_list) == 1:
                        _temp_list = re.split('=', data)
                    data_list.append(_temp_list)
                return data_list
            except Exception:
                log.error(f"转换数据{source},时发生错误，请检查数据")
                raise Exception(f"转换数据{source},时发生错误，请检查数据")
        return None
